package com.bbva.kyfb.kyfbbofo.implement;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.bbva.jee.arq.spring.core.contexto.ArqSpringContext;
import com.bbva.jee.arq.spring.core.gce.ExcepcionEjecucionAplicacion;
import com.bbva.jee.arq.spring.core.log.I18nLog;
import com.bbva.jee.arq.spring.core.log.I18nLogFactory;
import com.bbva.jee.arq.spring.core.util.excepciones.PropiedadNoEncontradaExcepcion;
import com.bbva.kyfb.kyfbdaofo.implement.ServicioAsistentesDao;
import com.bbva.kyfb.kyfbdaofo.interfaces.BitDao;
import com.bbva.kyfb.kyfbdto.firmas.errores.Errores_kyfb_servicios;
import com.bbva.kyfb.kyfbdtofo.AsuntoCruzadoDto;
import com.bbva.kyfb.kyfbdtofo.BdbziteDto;
import com.bbva.kyfb.kyfbdtofo.BuzonItem;
import com.bbva.kyfb.kyfbdtofo.FicheroRequest;
import com.bbva.kyfb.kyfbdtofo.ListaICDDto;
import com.bbva.kyfb.kyfbdtofo.RequestDto;
import com.bbva.kyfb.kyfbdtofo.ResponseDto;
import com.bbva.kyfb.kyfbdtofo.entitys.SfoDTO;
import com.bbva.kyfb.kyfbdtofo.firmas.errores.Errores_kyfbfo_servicios;
import com.bbva.kyfb.kyfbjpatlsb.dominiotlsb.Tbdbzbit;
import com.bbva.kyfb.kyfbjpatlsb.dominiotlsb.TbdbzbitPK;
import com.bbva.kyfb.kyfbofo.abstracts.ExecuteBOAbstract;
import com.bbva.kyfb.kyfbofo.interfaces.ExecuteFileBO;
import com.bbva.kyfb.kyfbutils.constantes.ConstantesFO;
import com.bbva.kyfb.kyfbutils.constantes.UtilFO;

@Service
public class FicherosEjecucionBO extends ExecuteBOAbstract implements
		ExecuteFileBO {

	@Autowired
	private ServicioAsistentesDao servicioAsistentesDao;

	@Resource(name = "ordenBancoMap")
	private Map<String, String> ordenBancoMap;
	
	@Autowired
	private BuzonItem buzonItem;
	
	@Autowired
	private BitDao bitDao;
	
	private static final I18nLog log = I18nLogFactory.getLogI18n(FicherosEjecucionBO.class);

	private String sSufijoFichLento;
	private String estadoFichero = ConstantesFO.LOGON_FINAL_FICH;
	private int via = 0;
	private long lSize = 0;
	private String sRuta = "";
	private int modoAsunto = 0;
	
	/**
	 * Este metodo ejecuta la parte complementaria a la ejecucion de un fichero.
	 * Actualiza el buzon y crea el objeto señuelo.
	 * 
	 * @param FicheroRequest
	 * @return ResponseDto
	 */
	@Override
	public ResponseDto process(RequestDto aRequestDto) {
		try {
			FicheroRequest aFicheroRequest = (FicheroRequest) aRequestDto;
			if (esMismoBanco(getSfoDTO().getDesAsunacce(), aFicheroRequest)) {
				actualizaBuzon(aFicheroRequest);
				okFicheroSenyueloENVCreado(getSfoDTO().getDesNomfich(),
						aFicheroRequest.getCodClieCash(), aFicheroRequest);
			} else {
				// TODO: falta la migracion de la om de arquitectura
				envioFicheroGlobal(getSfoDTO(), aFicheroRequest);
			}
			
			getResponseDto().setAssistantCodError(ConstantesFO.COD_ERROR_SUCCESSFUL);
		}
		catch(Exception exception) {
			getResponseDto().setAssistantCodError(ConstantesFO.COD_ERROR);
			getResponseDto().setError(Errores_kyfb_servicios.ERROR_AL_LANZAR_ASISTENTE);
		}
		
		return getResponseDto();
	}

	/**
	 * Este metodo consulta si es un envio al mismo banco.
	 * 
	 * @param cuentaEmisora
	 *            , tipoOrden
	 * @return true or false
	 */
	public boolean esMismoBanco(String cuentaEmisora,
			FicheroRequest ficheroRequest) {

		boolean esMismoBanco = false;
		String bancoAsunto = "";
		bancoAsunto = getBancoAsunto(cuentaEmisora, ficheroRequest);

		Integer ibancoRef = Integer.valueOf(ficheroRequest.getBancoInterno());
		Integer ibancoAsunto = new Integer(bancoAsunto);
		// Solo se comprueba cuando la referencia es de España o REd exterior
		if (ibancoAsunto.intValue() == 1) {
			if (ibancoRef.intValue() == 1) {
				if (esRefAuxiliar(ficheroRequest.getTipoOrden(),
						ficheroRequest.getSubproducto())) {
					ibancoAsunto = Integer.valueOf("1");
					ibancoRef = Integer.valueOf("1");
				} else {
					ibancoAsunto = Integer.valueOf("1");
					ibancoRef = Integer.valueOf("2");

				}
			}
		}

		if (ibancoAsunto.equals(ibancoRef)) {
			log.info("************Es mismo Banco************");
			esMismoBanco = true;
		} else {
			log.info("************No es mismo Banco************");
			esMismoBanco = false;
		}

		return esMismoBanco;
	}

	/**
	 * Este método comprueba el pais de la referencia y de la orden.
	 * 
	 * @exception com.grobbva.ii.sf.base.BbvaException
	 *                La descripción de excepción.
	 */
	public boolean esRefAuxiliar(String tipoOrden, String subProducto) {

		boolean respuesta = false;
		int subproducto2 = Integer.parseInt(subProducto);
		String paisRef = "";

		switch (subproducto2) {
		case 2:

			paisRef = "cw";
			break;

		case 8:

			paisRef = "fr";
			break;

		case 10:

			paisRef = "gb";
			break;

		case 12:

			paisRef = "be";
			break;

		case 16:

			paisRef = "hk";
			break;

		case 18:

			paisRef = "us";
			break;

		default:
			paisRef = "es";

		}

		String paisOrden = "";

		if (UtilFO.esClaseRedExterior(tipoOrden)) {
			paisOrden = UtilFO.getPaisClaseRedExterior(tipoOrden);
		} else {
			paisOrden = "es";
		}

		if (paisOrden.equals(paisRef)) {
			respuesta = true;
		}

		return respuesta;

	}

	/**
	 * Transforma el atributo timestamp con formato aaaammddhhmmssccccccccc. al
	 * formato aaaa-mm-dd hh:mm:ss.cccccc para poder crear un objeto Timestamp.
	 * 
	 * @return java.lang.String
	 */
	public static String getTimeStamp() {
		SimpleDateFormat template = new SimpleDateFormat();
		template.applyPattern("yyyy-MM-dd-HH.mm.ss.SSS");
		long lCurrentTime = System.currentTimeMillis();
		Date timeStamp = new Date(lCurrentTime);
		String timeStampFormateado = template.format(timeStamp);
		timeStampFormateado += "000";
		return timeStampFormateado;

	}
	
	@Transactional("transactionManagerTLSB")
	private int actualizaBuzon(RequestDto aFicheroRequest) {
		buzonItem.setCanal(Integer.valueOf(aFicheroRequest.getCanal()));
		buzonItem.setBancoInterno(Integer.valueOf(aFicheroRequest.getBancoInterno()));
		buzonItem.setLogon(ConstantesFO.LOGON_FINAL_FICH);
		buzonItem.setNumItem(aFicheroRequest.getNumItem());
		buzonItem.setXtibuzon(ConstantesFO.XTI_BUZON);
		buzonItem.setFecha(getTimeStamp());

		int resultado = bitDao.actualizarBuzon(buzonItem);
		
		if (resultado > 0) {
			log.info("******************Se ha actualizado el buzon******************");
			log.info(buzonItem.toString());
			return resultado;
		} else {
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_ACTUALIZANDO_REGISTRO);
		}
	}
	
	/**
	 * dejo este metodo temporarlmente, en caso que nos llamemos directamente y no
	 * hayamos pasado por firma, en la bit habra que hacer un insert ficticion, para 
	 * posteriormente poder actualizarlo.
	 * 
	 * revisar la query del populate para pode simular lo correctamete
	 */
	@SuppressWarnings("unused")
	private void insertBit() {
		try {
		
		Tbdbzbit bit = new Tbdbzbit();
//		Short codCanaldi, Short codBancoint, String codLogonapl, Character xtiBuzon, BigDecimal qnuNumitem
		TbdbzbitPK id = new TbdbzbitPK(Short.valueOf(String.valueOf(buzonItem.getCanal())), Short.valueOf(String.valueOf(buzonItem.getBancoInterno())), buzonItem.getLogon(), buzonItem.getXtibuzon(), new BigDecimal(buzonItem.getNumItem()));
		bit.setId(id);
		
//		SimpleDateFormat sdf = new SimpleDateFormat(
//				"yyyy-MM-dd-HH.mm.ss.SSS");
//		try {
//			bit.setTimFirma(sdf.parse(buzonItem.getFecha()));
//		} catch (ParseException e) {
//		}
		
		
		bit.setAudFmodific(new Date());
		bit.setAudUsuario("xatlsb1d");
		bit.setFecRecepcio(new Date());
		bit.setHmsRecepcio(new Date());
		bit.setCodPid((short) 0);
		
		bitDao.insert(bit);
//		Tbdbzbit update = bitDao.update(bit);			
		bitDao.flush();
		
//		@SuppressWarnings("unused")
	}
	catch(Exception e) {
		/*
		 la excepcion es: org.hibernate.exception.ConstraintViolationException: could not insert: [com.bbva.kyfb.kyfbjpatlsb.dominiotlsb.Tbdbzbit]; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not insert: [com.bbva.kyfb.kyfbjpatlsb.dominiotlsb.Tbdbzbit]

		 
		la excepcion es: Validation failed for classes 
		[com.bbva.kyfb.kyfbjpatlsb.dominiotlsb.Tbdbzbit] during persist time for groups [javax.validation.groups.Default, ]
		
		List of constraint violations:[
			ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=audFmodific, rootBeanClass=class com.bbva.kyfb.kyfbjpatlsb.dominiotlsb.Tbdbzbit, messageTemplate='{javax.validation.constraints.NotNull.message}'}
			ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=audUsuario, rootBeanClass=class com.bbva.kyfb.kyfbjpatlsb.dominiotlsb.Tbdbzbit, messageTemplate='{javax.validation.constraints.NotNull.message}'}
			ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=fecRecepcio, rootBeanClass=class com.bbva.kyfb.kyfbjpatlsb.dominiotlsb.Tbdbzbit, messageTemplate='{javax.validation.constraints.NotNull.message}'}
			ConstraintViolationImpl{interpolatedMessage='may not be null', propertyPath=hmsRecepcio, rootBeanClass=class com.bbva.kyfb.kyfbjpatlsb.dominiotlsb.Tbdbzbit, messageTemplate='{javax.validation.constraints.NotNull.message}'}
		]
		*/
		
		System.out.println(e);
	}
	
	}
	
	private void okFicheroSenyueloENVCreado(String nombreFichero,
			String empresa, FicheroRequest ficheroRequest) {

		String nombreFicheroSenyuelo = "";
		Date fecha = new Date();
		int iVia;

		try {
			String path = File.separator + ConstantesFO.BUZON_DEFECTO
					+ File.separator + UtilFO.calcularRutaBuzon(empresa)
					+ File.separator;
			
			File file = new File(path + nombreFichero);
			
			log.info("Fichero => "+file.getAbsolutePath());
			
			lSize = new Long(file.length());

			// Obtenemos el pais para tratamientos posteriores
			List<ListaICDDto> listaICD = ListaICDDto
					.parseListaICDs(servicioAsistentesDao
							.getListaICD(ficheroRequest.getBancoInterno()));

			String paisbbv = listaICD.get(0).getPaisoalf().toString();

			List<Object[]> lControAgrupacionBuzones = servicioAsistentesDao
					.getListaControlAgrupacionesBuzones(
							ficheroRequest.getTipoOrden(),
							ficheroRequest.getCanal(),
							ficheroRequest.getBancoInterno());

			iVia = consultaViaSeleccionada(lControAgrupacionBuzones.get(0),
					lSize);
			nombreFicheroSenyuelo = obtenerFicheroSenueloAplicacion(
					ficheroRequest.getCanal(),
					ficheroRequest.getBancoInterno(), String.valueOf(iVia),
					ficheroRequest.getAplicacion(), paisbbv);

			// ruta de ejemplo /de/tlsb/batch/es/dat/di/TLSB.00230001.S25600SENUELO 
			File senueloFile = new File(nombreFicheroSenyuelo);
			
			log.info("fichero senuelo => "+senueloFile.getAbsolutePath());

			if (!senueloFile.exists()) {
				log.info("*******Creamos el ficheo senuelo ya existe*******");
				FileWriter fileWriter = new FileWriter(nombreFicheroSenyuelo);
				PrintWriter printWriter = new PrintWriter(new BufferedWriter(fileWriter));
				// Grabamos sobre el fichero al menos nueve bytes.
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSS");
				printWriter.println(sdf.format(fecha));
				printWriter.close();
				fileWriter.close();
			}
			else {
				log.info("*******El ficheo senuelo ya existe*******");
			}

		} catch (Exception e) {
			log.error("ERROR_CREANDO_FICHERO_SENUELO");
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_CREANDO_FICHERO_SENUELO);
		}

	}

	private int consultaViaSeleccionada(Object[] o, long tamanoFichero) {
		int iCodVia = Integer.valueOf(o[4].toString());
		int tamannoCorte = Integer.valueOf(o[5].toString());
		if (tamannoCorte <= 0 || tamannoCorte > 0
				&& tamanoFichero <= tamannoCorte) {
			iCodVia = Integer.valueOf(o[4].toString());
		} else if (tamannoCorte > 0 && tamanoFichero >= tamannoCorte) {
			iCodVia = Integer.valueOf(o[6].toString());
		}
		return iCodVia;
	}

	private String obtenerFicheroSenueloAplicacion(String canal,
			String bancoInt, String via, String aplicacion, String pais) {
		String sennueloApp = null;
		List<Object[]> lExterna = servicioAsistentesDao
				.getListaExternalizacion(bancoInt);

		Object[] aObjeto = lExterna.get(0);

		sennueloApp = aObjeto[4].toString();

		try {
			sennueloApp = UtilFO.strTran(sennueloApp, "%entorno%",
					ArqSpringContext.getPropiedad("VAR.ENTORNO"));
		} catch (PropiedadNoEncontradaExcepcion e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		sennueloApp = UtilFO.strTran(sennueloApp, "%aplicacionDir%",
				aplicacion.toLowerCase());
		sennueloApp = UtilFO.strTran(sennueloApp, "%pais%", pais.toLowerCase());
		sennueloApp = UtilFO.strTran(sennueloApp, "%aplicacion%",
				aplicacion.toUpperCase());
		sennueloApp = UtilFO.strTran(sennueloApp, "%canal%", canal);
		sennueloApp = UtilFO.strTran(sennueloApp, "%bancoInt%", bancoInt);
		sennueloApp = UtilFO.strTran(sennueloApp, "%via%", via);

		return sennueloApp;
	}

	private void envioFicheroGlobal(SfoDTO sfoDto,
			FicheroRequest aFicheroRequest) {

		int validacion = 0;
		int iBancoAsuntoCruzado = 0;
		int iServicioOrigen = 0;
		//List<Object[]> lAsuntoCruzado = null;
		Vector<String> datosAsuntoCruzado = new Vector<String>();
		AsuntoCruzadoDto asuntoCruzadoDto = null;
		// Si el asunto viene vacio tendremos que comprobar el banco del asunto,
		// pues
		// puede darse el caso en el que una referencia Principal envie un
		// fichero de una
		// referencia Auxiliar.
		int bancoAsunto = Integer.valueOf(getBancoAsunto(sfoDto.getDesAsunacce(), aFicheroRequest));
		if (sfoDto.getDesAsunacce() == null
				|| sfoDto.getDesAsunacce().equals("")) {
			if (bancoAsunto == 0) {
				validacion = validarFicheroEnEntrada(aFicheroRequest,
						sfoDto.getDesNomfich(), sfoDto.getCodProdserv());
				envioMismaReferencia(sfoDto.getQnuNumitem().longValue(), aFicheroRequest, sfoDto.getDesNomfich(), 
						String.valueOf(sfoDto.getCodProdserv()));
			}
			else
			{
				// No conocemos el asunto, por lo que deberemos buscarlo para el banco del asunto que referencia
				modoAsunto = 0;
				datosAsuntoCruzado = getDatosAsuntoCruzado(aFicheroRequest, sfoDto.getDesAsunacce());
				asuntoCruzadoDto = buscarAsuntoCruzado(aFicheroRequest, datosAsuntoCruzado, modoAsunto);
				
				// Tratandose de una referencia Principal, puede ocurrir que envíe un fichero de una referencia Auxiliar
				validacion = tratarEnvioCruce(asuntoCruzadoDto, aFicheroRequest, sfoDto);
			}
		}
		else{
			if(bancoAsunto == 0){
				modoAsunto = 1;
				asuntoCruzadoDto = buscarAsuntoCruzado(aFicheroRequest, datosAsuntoCruzado, modoAsunto);
				if(asuntoCruzadoDto == null){
					validacion = validarFicheroEnEntrada(aFicheroRequest,
							sfoDto.getDesNomfich(), sfoDto.getCodProdserv());
					envioMismaReferencia(sfoDto.getQnuNumitem().longValue(), aFicheroRequest, sfoDto.getDesNomfich(), 
							String.valueOf(sfoDto.getCodProdserv()));
				}
				else{
					// Comprobamos que el asunto que nos informan realmente pertenece a una referencia Principal
					iBancoAsuntoCruzado = Integer.valueOf(asuntoCruzadoDto.getCod_BancoAsu());   //lAsuntoCruzado.get(0)[1].toString());
//					Accedemos a la tabla de ordenes para obtener el servicio origen
					iServicioOrigen = getServicioOrigen(aFicheroRequest);
					if (asuntoEnReferenciaOrigen(aFicheroRequest, iBancoAsuntoCruzado, iServicioOrigen, 
							Integer.valueOf(sfoDto.getDesAsunacce())))
					{
						validacion = tratarEnvioCruce(asuntoCruzadoDto, aFicheroRequest, sfoDto);
					}
					else
					{
//						EL ASUNTO SUMINISTRADO NO PERTENECE A LA REFERENCIA NI COMO PROPIO NI COMO CRUZADO
						// TODO: poner error bien
						throw new ExcepcionEjecucionAplicacion(
								Errores_kyfbfo_servicios.ERROR_EN_SQL);
					}
					
				}
			}
			else
			{
				modoAsunto = 2;
				asuntoCruzadoDto = buscarAsuntoCruzado(aFicheroRequest, datosAsuntoCruzado, modoAsunto);
				iBancoAsuntoCruzado = Integer.valueOf(asuntoCruzadoDto.getCod_BancoAsu());
//				Accedemos a la tabla de ordenes para obtener el servicio origen
				iServicioOrigen = getServicioOrigen(aFicheroRequest);
//				 Miramos si el asunto está en TLNESER para el origen. Da igual si es local o cruzado.
				if (asuntoEnReferenciaOrigen(aFicheroRequest, iBancoAsuntoCruzado, iServicioOrigen, 
						Integer.valueOf(sfoDto.getDesAsunacce())))
				{
					datosAsuntoCruzado = getDatosAsuntoCruzado(aFicheroRequest, sfoDto.getDesAsunacce());
//					Miramos si el asunto está en la tabla TLNERFC (asuntos cruzados).
					asuntoCruzadoDto = buscarAsuntoCruzado(aFicheroRequest, datosAsuntoCruzado, modoAsunto);
					
					// Tratandose de una referencia Principal, puede ocurrir que envíe un fichero de una referencia Auxiliar
					validacion = tratarEnvioCruce(asuntoCruzadoDto, aFicheroRequest, sfoDto);
				}
				else
				{
//					EL ASUNTO SUMINISTRADO NO PERTENECE A LA REFERENCIA NI COMO PROPIO NI COMO CRUZADO
					// TODO: poner error bien
					throw new ExcepcionEjecucionAplicacion(
							Errores_kyfbfo_servicios.ERROR_EN_SQL);
				}
			}
		}
		
		if (validacion != 0)
		{
			// Si el fichero ha sido validado y ademas ha dado error, mostramos mensaje al cliente
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);			
		}

	}

	private String getBancoAsunto(String cuentaEmisora,
			RequestDto aFicheroRequest) {

		String bancoAsunto;
		bancoAsunto = ordenBancoMap.get(aFicheroRequest.getTipoOrden());
		if (ordenBancoMap == null) {
			bancoAsunto = "-1";
		}
		if (bancoAsunto.equals("-1")) {
			// Sacamos el banco interno de sesion
			bancoAsunto = aFicheroRequest.getBancoInterno();
		}

		if (UtilFO.esClaseInternacional(aFicheroRequest.getTipoOrden())) {
			if (cuentaEmisora.indexOf("ES") != -1) {
				bancoAsunto = "1";
			} else if (cuentaEmisora.indexOf("PT") != -1) {
				bancoAsunto = "73";
			}
		}

		return bancoAsunto;

	}

	/**
	 * Inserte aquí la descripción del método. Fecha de creación: (19/12/2005
	 * 18:06:50)
	 * 
	 * @exception com.grupobbva.ii.sf.base.BbvaNGException
	 *                La descripción de excepción.
	 */
	public int validarFicheroEnEntrada(FicheroRequest ficheroRequest,
			String nombreFichero, Short productoServ) {
		try {
			int validacion = 0;

			String sRuta = File.separator + ConstantesFO.BUZON_DEFECTO
					+ File.separator
					+ UtilFO.calcularRutaBuzon(ficheroRequest.getCodClieCash())
					+ File.separator;
			File file = new File(sRuta + nombreFichero);
			long lSize = new Long(file.length());

			List<Object[]> lControAgrupacionBuzones = servicioAsistentesDao
					.getListaControlAgrupacionesBuzones(
							ficheroRequest.getTipoOrden(),
							ficheroRequest.getCanal(),
							ficheroRequest.getBancoInterno());

			via = consultaViaSeleccionada(lControAgrupacionBuzones.get(0),
					lSize);

			// Indicamos la condición de señuelo para ficheros lentos (Tamaño >
			// umbral)
			switch (via) {
			case 1: {
				sSufijoFichLento = ConstantesFO.SUFIJO_FICHERO_LENTO;
				break;
			}
			}

			// Si el fichero es PDTEFIRMAS o RECHAZOS no se valida
			// Igualmente no se valida cuando el fichero que se envia es como recepción. 
			// En la recepción el estado del fichero viene indicado con el logon del cliente (numérico).
			if (!estadoFichero.equals(ConstantesFO.ESTADO_PDTEFIRMAS) && !estadoFichero.equals(ConstantesFO.ESTADO_RECHAZOS) 
					&& !UtilFO.esNumerico(estadoFichero))
			{
				// Se valida el fichero a enviar
				validacion = validarFichero(ficheroRequest.getBancoInterno(),
						ficheroRequest.getTipoOrden(), sRuta);
				if (validacion == 0) {
					// Hay ficheros que tienen un tratamiento especial.
					List<Object[]> listaTratamientoFichero = servicioAsistentesDao
					.getListaTratamientoFichero(
							ficheroRequest.getBancoInterno(),
							ficheroRequest.getTipoOrden());

					if (ConstantesFO.DF_DESVIOBUZON.equals(listaTratamientoFichero.get(0)[2].toString().trim())) {
						desvioBuzones(ficheroRequest, via,
								listaTratamientoFichero.get(0), nombreFichero, lSize, productoServ, sRuta);
					} else {
						estadoFichero = ConstantesFO.ESTADO_RECHAZOS;
					}
				}	
			}

			return 0;

		} catch (Exception e) {
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
		}

	}

	private int validarFichero(String bancoInterno, String claseOrden,
			String ruta) {

		String sCabecera = "";
		int iError = 0;

		List<Object[]> listaFormatoFichero = servicioAsistentesDao
				.getListaFormatoFichero(bancoInterno, claseOrden);

		if (listaFormatoFichero.get(0) != null) {

			sCabecera = listaFormatoFichero.get(0)[3].toString().trim();
			iError = validaEstructura(sCabecera, ruta);

		}

		return iError;
	}

	private int validaEstructura(String cabecera, String rutaFichero) {

		int error = 0;
		String sLinea;

		try {
			File fIN = new File(rutaFichero);
			if (fIN.exists()) {
				FileReader frIN = new FileReader(fIN);
				BufferedReader brIN = new BufferedReader(frIN);

				// Leemos la primera linea y comprobamos que es una linea apta.

				sLinea = brIN.readLine();
				if (cabecera.equals(sLinea.substring(0, cabecera.length()))) {
					error = 0;
				} else {
					error = 1;
				}
			}
		} catch (Exception e) {
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
		}

		return error;

	}

	private void desvioBuzones(FicheroRequest ficheroRequest, int via, Object[] o, String nombreFichero, long lSize, Short productoServ, 
			String pathBuzonOrigen) {

		long numItem = 0L;
		String sFecha = "";
		String sHora = "";
		int iCodErr = 0;
		String canalbancologonDesvio = "";
		String pathBuzonDesvio = "";
		String nombreSinExtension = "";
		String sTimeStamp = "";
		SimpleDateFormat FORMAT_yyyyMMddHHmmssSSSSSS = new SimpleDateFormat("yyyyMMddHHmmssSSSSSS");
		String extension = "";
		
		Date ahora = new Date();
		SimpleDateFormat fecha = new SimpleDateFormat("yyyy-MM-dd");
		SimpleDateFormat hora = new SimpleDateFormat("HH:mm:ss");

		numItem = generarNumeroItem();
		sFecha = fecha.format(ahora);
		sHora = hora.format(ahora);

		iCodErr = servicioAsistentesDao.altaBuzonIt(ficheroRequest, "C",
				numItem, sFecha, sHora, via);
		if (iCodErr >= 1) {
			canalbancologonDesvio = ficheroRequest.getCanal()
					+ ficheroRequest.getBancoInterno() + o[4].toString();

			List<ListaICDDto> listaICD = ListaICDDto
					.parseListaICDs(servicioAsistentesDao
							.getListaICD(ficheroRequest.getBancoInterno()));

			try {
				pathBuzonDesvio = listaICD.get(0).getsIcdDesPathbuzo()
						+ UtilFO.calcularRutaBuzon(canalbancologonDesvio)
						+ canalbancologonDesvio
						+ System.getProperty("file.separator");
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			// Obtenemos el nombre del fichero sin extension.
			nombreSinExtension = nombreFichero.substring(0, nombreFichero.indexOf("."));
			//Obtenemos fecha y hora del envio del fichero.
			sTimeStamp = nombreFichero.substring(nombreFichero.indexOf(".")+4);
			if (sTimeStamp.equals(""))
			{
				sTimeStamp = FORMAT_yyyyMMddHHmmssSSSSSS.format(new java.util.Date());
			}
			
			// Obtenemos la extension del fichero.
			extension = nombreFichero.substring(nombreFichero.indexOf("."), nombreFichero.indexOf(".")+3);
			
			BdbziteDto ite = new BdbziteDto();
			ite.setQNU_NUMITEM(numItem);
			ite.setDES_NOMBRE(nombreSinExtension);
			ite.setDES_NOMFICHE(nombreFichero);
			ite.setQNU_SIZE(lSize);
			ite.setTIM_TIMESTAM(obtenerTimestamp(sTimeStamp));
			ite.setDES_TIPFICHE("");
			ite.setDES_CABECER1("");
			ite.setDES_REFERENC("");
			ite.setCOD_TIPDATO2("");
			ite.setDES_USUFIRMA("");
			ite.setQNU_COPIA2(1L);
			ite.setDES_PATH(pathBuzonDesvio);
			ite.setCOD_COMREFEX(extension);
			ite.setDES_EMISOR(ficheroRequest.getCanal() + ficheroRequest.getBancoInterno() + ConstantesFO.CODIGO_LOGON_APL);
			ite.setFEC_ENVIO(sFecha);
			ite.setHMS_ENVIO1(sHora);
			ite.setCOD_BANCOPR(Integer.valueOf(ficheroRequest.getBancoInterno()));
			ite.setCOD_PRODSERV(Integer.valueOf(productoServ));
			ite.setCOD_SUBPRODU(Integer.valueOf(ficheroRequest.getSubproducto()));
			
			servicioAsistentesDao.altaBuzonIte(ite);
			// Mover el fichero del buzon de origen al buzon de destino
			copiaFichero(pathBuzonOrigen + nombreFichero, pathBuzonDesvio + nombreFichero);
			
		}
	}

	/**
	 * Inserte aquí la descripción del método. Fecha de creación: (13/05/2002
	 * 16:45:32)
	 * 
	 * @exception java.lang.Exception
	 *                La descripción de excepción.
	 */
	protected long generarNumeroItem() {
		try {
			Date hoy = new Date();
			long miliSeg = hoy.getTime();

			// Generamos un número de item de 12 cifras a partir del día de hoy
			// desechando el primer dígito.
			// La suma que se le hace es para empezar en un número posterior al
			// más alto que tiene la tabla actualmente.
			miliSeg = (miliSeg + (90000000000L)) % 1000000000000L;
			return miliSeg;
		} catch (Exception e) {
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
		}
	}
	
	/**
	 * Inserte aquí la descripción del método.
	 * Fecha de creación: (07/07/2003 14:13:08)
	 * @return java.sql.Timestamp
	 * @exception com.grupobbva.ii.sf.base.BbvaNGException La descripción de excepción.
	 */
	public Timestamp obtenerTimestamp(String sTimeStamp)
	{
		GregorianCalendar gregorianCalendar = new GregorianCalendar();
		
		gregorianCalendar.set(gregorianCalendar.YEAR, Integer.parseInt(sTimeStamp.substring(0,4)));
		gregorianCalendar.set(gregorianCalendar.MONTH, Integer.parseInt(sTimeStamp.substring(4,6))-1);
		gregorianCalendar.set(gregorianCalendar.DAY_OF_MONTH, Integer.parseInt(sTimeStamp.substring(6,8)));
		gregorianCalendar.set(gregorianCalendar.HOUR_OF_DAY, Integer.parseInt(sTimeStamp.substring(8,10)));
		gregorianCalendar.set(gregorianCalendar.MINUTE, Integer.parseInt(sTimeStamp.substring(10,12)));
		gregorianCalendar.set(gregorianCalendar.SECOND, Integer.parseInt(sTimeStamp.substring(12,14)));
		gregorianCalendar.set(gregorianCalendar.MILLISECOND, Integer.parseInt(sTimeStamp.substring(14)));

		return new Timestamp(gregorianCalendar.getTime().getTime());
	}
	
	/**
	 * Insert the method's description here.
	 * Creation date: (10/3/01 5:14:49 PM)
	 * @param ficheroOrigen java.lang.String
	 * @param ficheroDestino java.lang.String
	 * @exception java.io.IOException The exception description.
	 */
	public static void copiaFichero(String ficheroOrigen, String ficheroDestino){

	    File objFicheroOrigen = null;
	    // File directorioOrigen = null;
	    File objFicheroDestino = null;
	    File directorioDestino = null;

	    BufferedInputStream bufferedinputstream = null;
	    BufferedOutputStream bufferedoutputstream = null;
	    String nombreSistemaOperativo = System.getProperty("os.name");
	    int permisos = 0;
	    String comando = "";

	    //En sistemas UNIX para poder copiar un fichero necesito permiso de ejecucion sobre el directorio del que copio y de lectura sobre el fichero.
	    //En sistemas UNIX para poder copiar un fichero necesito permiso de ejecucion y escritura sobre el directorio al que copio.
	    ficheroOrigen = compruebaNombreDirectorio(ficheroOrigen);
	    objFicheroOrigen = new File(ficheroOrigen);

	    ficheroDestino = compruebaNombreDirectorio(ficheroDestino);
	    objFicheroDestino = new File(ficheroDestino);

	    //Comprobamos si lo que se ha pasado como parámetro es realmente un fichero 
	    //Tambien comprobamos que tenemos permiso de ejecucion sobre el directorio si estamos en UNIX.
	    if (!objFicheroOrigen.isFile()) {
	        System.out.println(
	            "APIComandos: El parámetro "
	                + objFicheroOrigen
	                + " no es un fichero o no existe o no tiene permiso de ejecucion sobre el directorio si es un sistema UNIX");
	    }
	    if (!objFicheroOrigen.canRead()) {
	        System.out.println(
	            "APIComandos: No tiene permiso de lectura sobre el fichero "
	                + objFicheroOrigen);

	    }
	    
	    directorioDestino = new File(objFicheroDestino.getParent());

	    // Comprobamos si tengo permiso de escritura sobre el directorio.

	    if (!directorioDestino.canWrite()) {
	        System.out.println(
	            "APIComandos : No tiene permiso de escritura en el directorio "
	                + directorioDestino);
	    }
	    // Comprobamos si el fichero de destino existe y de ser asi lo borramos.

	    if (objFicheroDestino.isFile()) {
	        objFicheroDestino.delete();
	    }
	    //copiamos

	    try {

	        FileInputStream fileinputstream = new FileInputStream(ficheroOrigen);
	        FileOutputStream fileoutputstream = new FileOutputStream(ficheroDestino);
	        bufferedinputstream = new BufferedInputStream(fileinputstream);
	        bufferedoutputstream = new BufferedOutputStream(fileoutputstream);
	        int i = (int) objFicheroOrigen.length();

	        for (byte abyte0[] = new byte[i];
	            bufferedinputstream.read(abyte0, 0, i) != -1;
	            bufferedoutputstream.write(abyte0, 0, i));

	    } catch (Exception e) {
	    	// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
	    }

	    //Compuebo y modifico permisos del fichero si estoy en UNIX
	    try {
	        if (nombreSistemaOperativo.equals(ConstantesFO.NOMBRE_AIX)
	            || nombreSistemaOperativo.equals(ConstantesFO.NOMBRE_SOLARIS)) {

	            permisos = compruebaPermisos(ficheroOrigen);

	            comando = " chmod " + permisos + " " + ficheroDestino;

	            

	            Process proc = Runtime.getRuntime().exec(comando);
				proc.waitFor();
	            //System.out.println("Permisos " + compruebaPermisos(ficheroDestino));
	            if (permisos != compruebaPermisos(ficheroDestino)) {
	                System.out.println("APIComandos : Permisos incorrectos en el fichero destino");
	            }
	        }
	    } catch (Exception e) {
	        System.out.println(
	            "APIComandos : Error al intentar asignar permisos a los  ficheros");
	    }

	    //Cerramos los buffers

	    finally {
	        try {
	            if (bufferedinputstream != null)
	                bufferedinputstream.close();
	            if (bufferedoutputstream != null)
	                bufferedoutputstream.close();
	        } catch (Exception e) {
	        	// TODO: poner error bien
				throw new ExcepcionEjecucionAplicacion(
						Errores_kyfbfo_servicios.ERROR_EN_SQL);
	        }
	    }
	}
	
	/**
	 * Inserte aquí la descripción del método.
	 * Fecha de creación: (14/02/2001 8:27:22)
	 */
	private static String compruebaNombreDirectorio (String directorio){
		Character caracter = null;
		directorio.replace('\\', java.lang.System.getProperty("file.separator").charAt(0));
		directorio.replace('/', java.lang.System.getProperty("file.separator").charAt(0));
		return directorio;
	}
	
	/**
	 * Insert the method's description here.
	 * Creation date: (08-10-01 4:43:05 PM)
	 * @return int
	 * @param ficheroOrigen java.lang.String
	 */
	private static int compruebaPermisos(String ficheroOrigen){
		//Compuebo permisos del fichero si estoy en UNIX
		int permisos = 0;
		int pUsuario = 0;
		int pGrupo = 0;
		int pOtros = 0;
		int error = 0;
		InputStream stdin = null;
		InputStreamReader isr = null;
		BufferedReader br = null;
		String line = "";

		String comando = " ls -l " + ficheroOrigen;

		try{

			Process proc = Runtime.getRuntime().exec(comando);

			if (proc.waitFor() == 0) {

				stdin = proc.getInputStream();
				isr = new InputStreamReader(stdin);
				br = new BufferedReader(isr);

				line = br.readLine();

				// Construimos los permisos de usuario
				if (line.charAt(1) == 'r')
					pUsuario = 4;
				if (line.charAt(2) == 'w')
					pUsuario = pUsuario + 2;
				if (line.charAt(3) == 'x' || line.charAt(3) == 's')
					pUsuario = pUsuario + 1;

				// Construimos los permisos de grupo
				if (line.charAt(4) == 'r')
					pGrupo = 4;
				if (line.charAt(5) == 'w')
					pGrupo = pGrupo + 2;
				if (line.charAt(6) == 'x' || line.charAt(6) == 's')
					pGrupo = pGrupo + 1;

				//Construimos los permisos de otros
				if (line.charAt(7) == 'r')
					pOtros = 4;
				if (line.charAt(8) == 'w')
					pOtros = pOtros + 2;
				if (line.charAt(9) == 'x' || line.charAt(9) == 's')
					pOtros = pOtros + 1;
				permisos = pUsuario * 100 + pGrupo * 10 + pOtros;

				return permisos;
			}
		}
		catch(Exception e){
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
		}

		return error;
	}
	
	public void envioMismaReferencia(long qnuNumItem, FicheroRequest fr, String sNombreFichero, String productoServ) 
	{
		if (qnuNumItem == 0)
		{
			// Registramos el fichero.
			qnuNumItem = registrarFicheroOrigen((estadoFichero.equals(ConstantesFO.ESTADO_PDTEFIRMAS) || estadoFichero.equals(ConstantesFO.ESTADO_RECHAZOS) || 
					UtilFO.esNumerico(estadoFichero))?estadoFichero:ConstantesFO.LOGON_FINAL_FICH, fr, 
							sNombreFichero, productoServ);
		}
		else
		{
			//Si el estado del fichero es PDTEFIRMAS lo cambiamos a ORDENESCRC
			String logonEstado = obtenerEstadoFicheroLogico(qnuNumItem);
			if (logonEstado.trim().equals(ConstantesFO.ESTADO_PDTEFIRMAS)){
				RequestDto ficheroReq = new FicheroRequest();
				ficheroReq.setCanal(fr.getCanal());
				ficheroReq.setBancoInterno(fr.getBancoInterno());
				ficheroReq.setReferencia(fr.getReferencia());
				ficheroReq.setNumItem(String.valueOf(qnuNumItem));
				actualizaBuzon(ficheroReq);
			}
		}

		// Generamos el señuelo en agrupación.
		if (!UtilFO.esNumerico(estadoFichero) && estadoFichero.equals(ConstantesFO.LOGON_FINAL_FICH))
//			TODO probar y revisar si este metodo nos vale o hay que hacer uno nuevo
			okFicheroSenyueloENVCreado(sNombreFichero, fr.getCodClieCash(), fr);
	}
	
	protected long registrarFicheroOrigen(String logonFisico, FicheroRequest fr, String nombreFichero, String productoServ) 
	{
		long numItem = 0L;
		BuzonItem buzonItem = new BuzonItem();
		//Item item = new Item();
		String sFecha = "";
		String sHora = "";
		String sEmisor = "";
		Date ahora = new Date();
	    SimpleDateFormat fecha = new SimpleDateFormat("yyyy-MM-dd");
		SimpleDateFormat hora = new SimpleDateFormat("HH:mm:ss");
		String nombreSinExtension = "";
		String sTimeStamp = "";
		SimpleDateFormat FORMAT_yyyyMMddHHmmssSSSSSS = new SimpleDateFormat("yyyyMMddHHmmssSSSSSS");
		String extension = "";
		
		try 
		{
			// Preparamos los valores para el alta.
			sFecha = fecha.format(ahora);
			sHora = hora.format(ahora);

			if (UtilFO.esNumerico(logonFisico))
			{
				// caso particular en el que se desea que el fichero enviado quede en estado de recepción (Simulamos una desagrupación).
				sEmisor = fr.getCanal() + fr.getBancoInterno() + ConstantesFO.CODIGO_LOGON_APL;
			}
			else
			{
				sEmisor = fr.getCanal() + fr.getBancoInterno() + fr.getReferencia();
			}

			// Generamos el número de item.	
			numItem = generarNumeroItem();

			buzonItem.setNumItem(String.valueOf(numItem));
			buzonItem.setCanal(Integer.parseInt(fr.getCanal()));
			buzonItem.setBancoInterno(Integer.parseInt(fr.getBancoInterno()));
			buzonItem.setLogon(logonFisico);
			buzonItem.setFecha(sFecha);
			buzonItem.setHora(sHora);
			// Siempre le damos de alta como current.
			buzonItem.setXtibuzon(ConstantesFO.XTI_BUZON);

			// Indicar  la prioridad de ficheros (rapidos-0/lentos-1)
			buzonItem.setCodPid(Integer.valueOf(via));
			
			servicioAsistentesDao.altaBuzonIt(fr, String.valueOf(buzonItem.getXtibuzon()), Long.parseLong(buzonItem.getNumItem()), buzonItem.getFecha(), 
					buzonItem.getHora(), buzonItem.getCodPid());

			// Obtenemos el nombre del fichero sin extension.
			nombreSinExtension = nombreFichero.substring(0, nombreFichero.indexOf("."));
			//Obtenemos fecha y hora del envio del fichero.
			sTimeStamp = nombreFichero.substring(nombreFichero.indexOf(".")+4);
			if (sTimeStamp.equals(""))
			{
				sTimeStamp = FORMAT_yyyyMMddHHmmssSSSSSS.format(new java.util.Date());
			}
			
			// Obtenemos la extension del fichero.
			extension = nombreFichero.substring(nombreFichero.indexOf("."), nombreFichero.indexOf(".")+3);
			
			// Damos de alta en ite.
			BdbziteDto ite = new BdbziteDto();
			ite.setQNU_NUMITEM(numItem);
			ite.setDES_NOMBRE(nombreSinExtension);
			ite.setDES_NOMFICHE(nombreFichero);
			ite.setQNU_SIZE(lSize);
			ite.setTIM_TIMESTAM(obtenerTimestamp(sTimeStamp));
			ite.setDES_TIPFICHE("");
			ite.setDES_CABECER1("");
			ite.setDES_REFERENC("");
			ite.setCOD_TIPDATO2("");
			ite.setDES_USUFIRMA("");
			ite.setQNU_COPIA2(1L);
			ite.setDES_PATH(sRuta);
			ite.setCOD_COMREFEX(extension);
			ite.setDES_EMISOR(fr.getCanal() + fr.getBancoInterno() + ConstantesFO.CODIGO_LOGON_APL);
			ite.setFEC_ENVIO(sFecha);
			ite.setHMS_ENVIO1(sHora);
			ite.setCOD_BANCOPR(Integer.valueOf(fr.getBancoInterno()));
			ite.setCOD_PRODSERV(Integer.valueOf(productoServ));
			ite.setCOD_SUBPRODU(Integer.valueOf(fr.getSubproducto()));
			
			servicioAsistentesDao.altaBuzonIte(ite);
			
		}
//		TODO
//		catch (SQLException e)
//		{
//			if (e.getErrorCode()==-803)
//			{
//				return registrarFicheroOrigen((estadoFichero.equals("PDTEFIRMAS") || estadoFichero.equals("RECHAZOS") || 
//						Util.esNumerico(estadoFichero))?estadoFichero:"ORDENESCRC", fr, nombreFichero, productoServ);
//			}
//			else
//			{
//				// TODO: poner error bien
//				throw new ExcepcionEjecucionAplicacion(
//						Errores_kyfbfo_servicios.ERROR_EN_SQL);
//			}
//		} 
		catch (Exception e) 
		{	
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
		}
		return numItem;
	}
	
	public String obtenerEstadoFicheroLogico(long qnuNumItem)
	{
		try 
		{
			// Obtenemos el estado.
			List<BuzonItem> estadoFicheroLogico = BuzonItem.parseRegBuzon(servicioAsistentesDao.getEstadoFicheroLogico(qnuNumItem));
			return estadoFicheroLogico.get(0).getLogon();
		} 
		catch (Exception e) 
		{		
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
		}
	}
	
	public Vector<String> getDatosAsuntoCruzado(RequestDto fr, String cuentaEmisora){
		
		Vector<String> vDatos = new Vector<String>(); 
		String servicio = "";
		int iServicioGlobal = 0;
		String bancoAsunto = "";
		
		List<Object[]> lCodigoServicioGlobal = servicioAsistentesDao.getCodigoServicioGlobal(fr.getTipoOrden());
		iServicioGlobal = Integer.valueOf(lCodigoServicioGlobal.get(0)[0].toString());
		
		List<Object[]> lServicioPermitidoCruzar = servicioAsistentesDao.getListaServicioPermitidoCruzar(iServicioGlobal, 
				Integer.valueOf(fr.getBancoInterno()));
		if (lServicioPermitidoCruzar == null)
		{
			servicio = ordenBancoMap.get(fr.getTipoOrden());
		}
		else
		{
			servicio = lServicioPermitidoCruzar.get(0)[2].toString();
		}
		
		bancoAsunto = getBancoAsunto(cuentaEmisora, fr);
		
		vDatos.add(servicio);
		vDatos.add(cuentaEmisora);
		vDatos.add(bancoAsunto);
		
		return vDatos;
		
	}
	
	
	public AsuntoCruzadoDto buscarAsuntoCruzado(FicheroRequest aFicheroRequest, Vector<String> datosAsuntoCruzado, int modoAsunto){

		List<AsuntoCruzadoDto> listaAsuntoCruzado = null;
		listaAsuntoCruzado = AsuntoCruzadoDto
				.parseListaAsuntoCruzado(servicioAsistentesDao
						.getListarAsuntoCruzado(aFicheroRequest,
								datosAsuntoCruzado, modoAsunto));

		return listaAsuntoCruzado.get(0);
		
	}
	
	public int tratarEnvioCruce(AsuntoCruzadoDto asuntoCruzadoDto, FicheroRequest aFicheroRequest, SfoDTO sfoDto)
	{
		int validacion = 0;
		int modoValidacion = 1;
		FicheroRequest ficheroRequest = new FicheroRequest();
		String bancoInternoOrigen = "";
		
		try
		{
			// Si es un asunto cruzado.
			if (asuntoCruzadoDto!= null)
			{
				bancoInternoOrigen = aFicheroRequest.getBancoInterno();
				// Almacenamos los datos del destino del fichero.
				ficheroRequest = almacenaDatosDestino(asuntoCruzadoDto, aFicheroRequest);

//				// Para obtener el cod_pid en referencias cruzadas, debemos informar del canal banco destino.
//
//				setICanalPID(iCanalDestino);
//				setIBancoInternoPID(iBancoInternoDestino);
//				
//				// Modo de validación de ficheros cruzado, le informamos del banco propietario del fichero
//				vf.setModoValidar(modoValidacion);
//				vf.setBancoInt(iBancoInternoDestino);
					
				// Realizamos la validación del fichero con el banco destino que le corresponda
				validacion = validarFicheroEnEntrada(ficheroRequest, sfoDto.getDesNomfich(), Short.valueOf(ficheroRequest.getProducto()));
					
				// Si el banco Interno (ICD) destino es del ámbito en el que estamos => local.
				if (esLocal(ficheroRequest.getBancoInterno(), bancoInternoOrigen))
				{
					envioMismoAmbito(sfoDto.getQnuNumitem().longValue(), ficheroRequest, sfoDto.getDesNomfich(), ficheroRequest.getProducto());
				}
				else
				{
					envioEntreAmbitos(sfoDto.getQnuNumitem().longValue(), ficheroRequest, sfoDto.getDesNomfich(), ficheroRequest.getProducto());
				}
			}
			// Asunto local.
			else
			{
				validacion = validarFicheroEnEntrada(ficheroRequest, sfoDto.getDesNomfich(), Short.valueOf(ficheroRequest.getProducto()));
				envioMismaReferencia(sfoDto.getQnuNumitem().longValue(), aFicheroRequest, sfoDto.getDesNomfich(), String.valueOf(sfoDto.getCodProdserv()));
			}
		}
		catch (Exception e)
		{
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
		}	
		return validacion;
	}
	
	public FicheroRequest almacenaDatosDestino(AsuntoCruzadoDto asuntoCruzadoDto, FicheroRequest aFicheroRequest){
		
		aFicheroRequest.setCanal(String.valueOf(asuntoCruzadoDto.getCanal()));
		aFicheroRequest.setBancoInterno(String.valueOf(asuntoCruzadoDto.getBancoInterno()));
		aFicheroRequest.setReferencia(asuntoCruzadoDto.getLogon());
		aFicheroRequest.setProducto(String.valueOf(asuntoCruzadoDto.getProducto()));
		aFicheroRequest.setSubproducto(String.valueOf(asuntoCruzadoDto.getSubproducto()));
		aFicheroRequest.setBancoProducto(String.valueOf(asuntoCruzadoDto.getBancoProducto()));
		
		return aFicheroRequest;
		
	}
	
	protected boolean esLocal(String iBancoInternoDestino, String iBancoInternoOrigen) 
	{
		boolean esLocal = false;
		int ambitoOrigen = 0;
		int ambitoDestino = 0;
		try 
		{

			List<ListaICDDto> listaICD = ListaICDDto.parseListaICDs(servicioAsistentesDao
					.getListaICD(iBancoInternoOrigen));
			
			if (listaICD==null)
			{
				// TODO: poner error bien
				throw new ExcepcionEjecucionAplicacion(
						Errores_kyfbfo_servicios.ERROR_EN_SQL);
			}
			else
			{
				ambitoOrigen = listaICD.get(0).getServbad();
			}
			
			List<ListaICDDto> listaICDDestino = ListaICDDto.parseListaICDs(servicioAsistentesDao
					.getListaICD(iBancoInternoDestino));
			
			if (listaICDDestino==null)
			{
				// TODO: poner error bien
				throw new ExcepcionEjecucionAplicacion(
						Errores_kyfbfo_servicios.ERROR_EN_SQL);
			}
			else
			{
				ambitoDestino = listaICDDestino.get(0).getServbad();
			}
			
			esLocal = ambitoOrigen==ambitoDestino;
			
		}
		catch (Exception e) 
		{		
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
		}
		return esLocal;
	}
	
	public void envioMismoAmbito(long qnuNumItem, FicheroRequest fr, String nombreFichero, String productoServ) 
	{
		try 
		{
			if (qnuNumItem == 0)
			{
				// Registramos el fichero.
				qnuNumItem = registrarFicheroOrigen((estadoFichero.equals(ConstantesFO.ESTADO_PDTEFIRMAS) || estadoFichero.equals(ConstantesFO.ESTADO_RECHAZOS) || 
						UtilFO.esNumerico(estadoFichero))?estadoFichero:ConstantesFO.LOGON_FINAL_FICH, fr, nombreFichero, productoServ);
			}
			else
			{
				//Si el estado del fichero es PDTEFIRMAS lo cambiamos a ORDENESCRC
				String logonEstado = obtenerEstadoFicheroLogico(qnuNumItem);
				if (logonEstado.trim().equals(ConstantesFO.ESTADO_PDTEFIRMAS)){
					RequestDto ficheroReq = new FicheroRequest();
					ficheroReq.setCanal(fr.getCanal());
					ficheroReq.setBancoInterno(fr.getBancoInterno());
					ficheroReq.setReferencia(fr.getReferencia());
					ficheroReq.setNumItem(String.valueOf(qnuNumItem));
					actualizaBuzon(ficheroReq);
				}
			}


			// Se pasa el fichero a la Ref. Aux únicamente cuando lo solicite Ref. Ppal
			// No tiene sentido mover un fichero que aún no ha sido autorizado.
			if (estadoFichero.equals("ORDENESCRC"))
			{
				// Movemos el fichero origen.
				moverFicheroOrigen(qnuNumItem, fr, nombreFichero, productoServ);

				// Generamos el señuelo en agrupación.
				if (!UtilFO.esNumerico(estadoFichero) && estadoFichero.equals(ConstantesFO.LOGON_FINAL_FICH))
//					TODO probar y revisar si este metodo nos vale o hay que hacer uno nuevo. Metodo original generarSenuelo()
					okFicheroSenyueloENVCreado(nombreFichero, fr.getCodClieCash(), fr);
			}

		}
		catch (Exception e) 
		{
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
		}
	}
	
	protected void moverFicheroOrigen(long numitem, FicheroRequest aFicheroRequest, String nombreFichero, String producto) 
	{ 
		try 
		{
			// Cambiamos de estado al fichero lógico.
			actualizaEstadoFicheroLogico(aFicheroRequest, ConstantesFO.LOGON_MOVIDO_FICH);
			
			String ref = aFicheroRequest.getCanal() + aFicheroRequest.getBancoInterno() + aFicheroRequest.getReferencia(); 
			servicioAsistentesDao.actualizarBuzonITE(ref, numitem);
			
			// Registramos el fichero para el destino.
//			registrarFicheroDestino("ORDENESCRC");
			registrarFicheroDestino(estadoFichero, aFicheroRequest, nombreFichero, producto);

			//Movemos físicamente el fichero al destino.
//			moverADestino();
			
		}
		catch (Exception e) 
		{		
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
		}
	}
	
	@Transactional("transactionManagerTLSB")
	private void actualizaEstadoFicheroLogico(RequestDto aFicheroRequest, String estadoLogon) {

		BuzonItem buzon = new BuzonItem();
		buzon.setCanal(Integer.valueOf(aFicheroRequest.getCanal()));
		buzon.setBancoInterno(Integer.valueOf(aFicheroRequest.getBancoInterno()));
		buzon.setLogon(estadoLogon);
		buzon.setNumItem(aFicheroRequest.getNumItem());
		buzon.setXtibuzon(ConstantesFO.XTI_BUZON);
		buzon.setFecha(getTimeStamp());

		servicioAsistentesDao.actualizarBuzon(buzon);

	}
	
	protected void registrarFicheroDestino(String logonFisico, FicheroRequest fr, String nombreFichero, String productoServ) 
	{
		long numItem = 0L;
		BuzonItem buzonItem = new BuzonItem();
		//Item item = new Item();
		String sFecha = "";
		String sHora = "";
		String sEmisor = "";
		Date ahora = new Date();
	    SimpleDateFormat fecha = new SimpleDateFormat("yyyy-MM-dd");
		SimpleDateFormat hora = new SimpleDateFormat("HH:mm:ss");
		String nombreSinExtension = "";
		String sTimeStamp = "";
		SimpleDateFormat FORMAT_yyyyMMddHHmmssSSSSSS = new SimpleDateFormat("yyyyMMddHHmmssSSSSSS");
		String extension = "";
		
		try 
		{
			// Preparamos los valores para el alta.
			sFecha = fecha.format(ahora);
			sHora = hora.format(ahora);

			if (UtilFO.esNumerico(logonFisico))
			{
				// caso particular en el que se desea que el fichero enviado quede en estado de recepción (Simulamos una desagrupación).
				sEmisor = fr.getCanal() + fr.getBancoInterno() + ConstantesFO.CODIGO_LOGON_APL;
			}
			else
			{
				sEmisor = fr.getCanal() + fr.getBancoInterno() + fr.getReferencia();
			}

			// Generamos el número de item.	
			numItem = generarNumeroItem();

			buzonItem.setNumItem(String.valueOf(numItem));
			buzonItem.setCanal(Integer.parseInt(fr.getCanal()));
			buzonItem.setBancoInterno(Integer.parseInt(fr.getBancoInterno()));
			buzonItem.setLogon(logonFisico);
			buzonItem.setFecha(sFecha);
			buzonItem.setHora(sHora);
			// Siempre le damos de alta como current.
			buzonItem.setXtibuzon(ConstantesFO.XTI_BUZON);

			// Indicar  la prioridad de ficheros (rapidos-0/lentos-1)
			buzonItem.setCodPid(Integer.valueOf(via));
			
			servicioAsistentesDao.altaBuzonIt(fr, String.valueOf(buzonItem.getXtibuzon()), Long.parseLong(buzonItem.getNumItem()), buzonItem.getFecha(), 
					buzonItem.getHora(), buzonItem.getCodPid());

			// Obtenemos el nombre del fichero sin extension.
			nombreSinExtension = nombreFichero.substring(0, nombreFichero.indexOf("."));
			//Obtenemos fecha y hora del envio del fichero.
			sTimeStamp = nombreFichero.substring(nombreFichero.indexOf(".")+4);
			if (sTimeStamp.equals(""))
			{
				sTimeStamp = FORMAT_yyyyMMddHHmmssSSSSSS.format(new java.util.Date());
			}
			
			// Obtenemos la extension del fichero.
			extension = nombreFichero.substring(nombreFichero.indexOf("."), nombreFichero.indexOf(".")+3);
			
			// Damos de alta en ite.
			BdbziteDto ite = new BdbziteDto();
			ite.setQNU_NUMITEM(numItem);
			ite.setDES_NOMBRE(nombreSinExtension);
			ite.setDES_NOMFICHE(nombreFichero);
			ite.setQNU_SIZE(lSize);
			ite.setTIM_TIMESTAM(obtenerTimestamp(sTimeStamp));
			ite.setDES_TIPFICHE("");
			ite.setDES_CABECER1("");
			ite.setDES_REFERENC("");
			ite.setCOD_TIPDATO2("");
			ite.setDES_USUFIRMA("");
			ite.setQNU_COPIA2(1L);
			ite.setDES_PATH(sRuta);
			ite.setCOD_COMREFEX(extension);
			ite.setDES_EMISOR(fr.getCanal() + fr.getBancoInterno() + ConstantesFO.CODIGO_LOGON_APL);
			ite.setFEC_ENVIO(sFecha);
			ite.setHMS_ENVIO1(sHora);
			ite.setCOD_BANCOPR(Integer.valueOf(fr.getBancoInterno()));
			ite.setCOD_PRODSERV(Integer.valueOf(productoServ));
			ite.setCOD_SUBPRODU(Integer.valueOf(fr.getSubproducto()));
			
			servicioAsistentesDao.altaBuzonIte(ite);
			
		}
//		TODO
//		catch (SQLException e)
//		{
//			if (e.getErrorCode()==-803)
//			{
//				return registrarFicheroOrigen((estadoFichero.equals("PDTEFIRMAS") || estadoFichero.equals("RECHAZOS") || 
//						Util.esNumerico(estadoFichero))?estadoFichero:"ORDENESCRC", fr, nombreFichero, productoServ);
//			}
//			else
//			{
//				// TODO: poner error bien
//				throw new ExcepcionEjecucionAplicacion(
//						Errores_kyfbfo_servicios.ERROR_EN_SQL);
//			}
//		} 
		catch (Exception e) 
		{	
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
		}
	}
	
	public void envioEntreAmbitos(long qnuNumItem, FicheroRequest fr, String nombreFichero, String productoServ) 
	{
		if(qnuNumItem == 0){
			
			qnuNumItem = registrarFicheroOrigen((estadoFichero.equals(ConstantesFO.ESTADO_PDTEFIRMAS) || estadoFichero.equals(ConstantesFO.ESTADO_RECHAZOS) || 
					UtilFO.esNumerico(estadoFichero))?estadoFichero:ConstantesFO.LOGON_FINAL_FICH, fr, nombreFichero, productoServ);
		}
		else{
//			En principio no hace falta el logon.
			String logonEstado = obtenerEstadoFicheroLogico(qnuNumItem);
			RequestDto ficheroReq = new FicheroRequest();
			ficheroReq.setCanal(fr.getCanal());
			ficheroReq.setBancoInterno(fr.getBancoInterno());
			ficheroReq.setReferencia(fr.getReferencia());
			ficheroReq.setNumItem(String.valueOf(qnuNumItem));
			actualizaEstadoFicheroLogico(ficheroReq, estadoFichero);
		}
		
		// Se pasa el fichero a la Ref. Aux únicamente cuando lo solicite Ref. Ppal
		// No tiene sentido mover un fichero que aún no ha sido autorizado.
		if (estadoFichero.equals("ORDENESCRC"))
			// Movemos el fichero origen.
			distribuir(qnuNumItem, fr);
	}
	
	protected void distribuir(long numitem, RequestDto fr) 
	{ 
		try 
		{
			// Enviamos físicamente el fichero al destino.
			enviarADestino();

			// Cambiamos de estado al fichero lógico.
//			cambiarEstadoFicheroLogico(numitem,"ORDENESCRC_DISTRIB","ORDENESCRC_PDTEDIST");
			RequestDto ficheroReq = new FicheroRequest();
			ficheroReq.setCanal(fr.getCanal());
			ficheroReq.setBancoInterno(fr.getBancoInterno());
			ficheroReq.setReferencia(fr.getReferencia());
			ficheroReq.setNumItem(String.valueOf(numitem));
			actualizaEstadoFicheroLogico(ficheroReq, ConstantesFO.LOGON_DISTRIB_FICH);
		}
		catch (Exception e) 
		{		
			// TODO: poner error bien
			throw new ExcepcionEjecucionAplicacion(
					Errores_kyfbfo_servicios.ERROR_EN_SQL);
		}
	}
	
	protected void enviarADestino() 
	{
		// TODO: llama a  una tx revisar que datos se necesita y cual es. enviarADestino() - BDFVOmEnvioFicheroGlobal
	}
	
	protected boolean asuntoEnReferenciaOrigen(FicheroRequest ficheroRequest, int iBancoAsuntoCruzado, int iServicioOrigen, int asunto){
		boolean existe = false;
		List<Object[]> lasuntoEnReferenciaOrigen = servicioAsistentesDao.asuntoEnReferenciaOrigen(ficheroRequest, iBancoAsuntoCruzado, 
				iServicioOrigen, asunto);
		if(lasuntoEnReferenciaOrigen == null){
			existe = true;
		}
		else{
			existe = false;
		}
		
		return existe;
	}
	
	private int getServicioOrigen(RequestDto fr){
		List<Object[]> lCodigoServicioGlobal = servicioAsistentesDao.getCodigoServicioGlobal(fr.getTipoOrden());
		return Integer.valueOf(lCodigoServicioGlobal.get(0)[0].toString());
	}
	
}